using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;

namespace Publish.Services
{
    /// <summary>
    /// Xml简易操作类
    /// </summary>
    public class XmlService
    {
        #region Fields

        private const String FolderPath = "D:/Program Files/Config";//配置文件路径
        public const String FileName = "D:/Program Files/Config/Publish.config";
        
        private const String XmlVersionId = "00000000-0000-0000-0000-000000000015"; //用于判断是否重新生成Xml文件
        //private readonly Stream xmlStream;

        #endregion

        #region Constructors

        public XmlService()
        {
            CreateFile();//文件不存在则创建

            //加载放到这里是为了处理Xml文件不存在的问题
            //xmlStream = new MemoryStream(File.ReadAllBytes(FileName));
        }

        #endregion

        #region AppSettings

        /// <summary>
        /// 保存连接字符串信息
        /// </summary>
        /// <param name="entity">连接字符串信息</param>
        public void Create(AppSettings entity)
        {
            //新增一条记录
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(FileName);
            var data = xmlDoc.SelectSingleNode("Data");//找到根节点

            var appSettings = data.SelectSingleNode("AppSettings");//创建子节点 AppSettings
            var item = xmlDoc.CreateElement("Item");//创建子节点 Item

            item.SetAttribute("Id", entity.Id);
            item.SetAttribute("Value", entity.Value);

            appSettings.AppendChild(item);//子项添加到 AppSettings 节点中
            data.AppendChild(appSettings);//子项添加到 Data 根节点中
            xmlDoc.Save(FileName);//保存
        }

        /// <summary>
        /// 获取所有连接字符串（因为一个项目可能存在多个连接字符串所以这里返回集合）
        /// </summary>
        /// <returns></returns>
        public IList<AppSettings> GetAllAppSettings()
        {
            var list = new List<AppSettings>();
            var xmlDoc = new XmlDocument();

            xmlDoc.Load(FileName);
            var xmlList = xmlDoc.SelectSingleNode("Data/AppSettings").ChildNodes;

            foreach (XmlNode node in xmlList)
            {
                if (node.Attributes == null) continue;

                var entity = new AppSettings
                {
                    Id = node.Attributes["Id"].Value,
                    Value = node.Attributes["Value"].Value,
                };
                list.Add(entity);
            }
            return list;
        }

        #endregion

        #region Project

        /// <summary>
        /// 新增一条地址数据
        /// </summary>
        /// <param name="entity">项目地址信息</param>
        public void Create(Project entity)
        {
            //新增一条记录
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(FileName);
            var data = xmlDoc.SelectSingleNode("Data");//找到根节点

            var project = data.SelectSingleNode("Project");//找到子节点 Project
            var item = xmlDoc.CreateElement("Item");//创建子节点 Item

            item.SetAttribute("Id", entity.Id);
            item.SetAttribute("IsDefault", entity.IsDefault);
            item.SetAttribute("Path", entity.Path);

            project.AppendChild(item);//子项添加到 Project 节点中
            data.AppendChild(project);//子项添加到 Data 根节点中
            xmlDoc.Save(FileName);//保存

            Modify(entity);//这里主要是将其他的项目地址默认取消。
        }

        /// <summary>
        /// 编辑指定项
        /// </summary>
        /// <param name="entity">项目地址</param>
        public void Modify(Project entity)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(FileName);
            var list = xmlDoc.SelectSingleNode("Data/Project");
            foreach (XmlNode node in list)
            {
                //修改此节点的属性值
                if ((!String.IsNullOrEmpty(entity.Id) && entity.Id != Guid.Empty.ToString()//根据Id判断
                    && node.Attributes["Id"].Value.Equals(entity.Id, StringComparison.InvariantCultureIgnoreCase))
                    )
                {
                    node.Attributes["IsDefault"].Value = entity.IsDefault;
                }
                else node.Attributes["IsDefault"].Value = "0";//将其他项重置为 0
            }
            //要想使对xml文件所做的修改生效，必须执行以下Save方法
            xmlDoc.Save(FileName);
        }

        /// <summary>
        /// 获取所有项目地址数据
        /// </summary>
        /// <returns></returns>
        public IList<Project> GetAllProject()
        {
            var list = new List<Project>();
            var xmlDoc = new XmlDocument();

            xmlDoc.Load(FileName);
            XmlNodeList xmlList = null;
            try
            {
                xmlList = xmlDoc.SelectSingleNode("Data/Project").ChildNodes;
            }
            catch (Exception)
            {
                //这段代码后留一段时间，用来防止部分用户Xml结构不一致时使用
                xmlList = xmlDoc.SelectSingleNode("Data").ChildNodes;
            }

            foreach (XmlNode node in xmlList)
            {
                var entity = new Project
                {
                    Id = node.Attributes["Id"].Value,
                    IsDefault = node.Attributes["IsDefault"].Value,
                    Path = node.Attributes["Path"].Value,
                };
                list.Add(entity);
            }
            return list;
        }

        /// <summary>
        /// 删除指定项
        /// </summary>
        /// <param name="id">项目地址Id值</param>
        public void Remove(String id)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(FileName);
            var xmlNode = xmlDoc.SelectSingleNode(String.Format("Data/Project/Item[@Id='{0}']", id)) ??
                          xmlDoc.SelectSingleNode(String.Format("Data/Project/Item[@Path='{0}']", id));

            if (xmlNode == null) return;
            xmlNode.ParentNode.RemoveChild(xmlNode);//删除该项
            xmlDoc.Save(FileName);//保存
        }

        #endregion

        #region Files

        ///// <summary>
        ///// 保存文件版本信息，用于判断是否修改
        ///// </summary>
        ///// <param name="entity">连接字符串信息</param>
        //public void Create(Files entity)
        //{
        //    //新增一条记录
        //    var xmlDoc = new XmlDocument();
        //    xmlDoc.Load(FileName);
        //    var data = xmlDoc.SelectSingleNode("Data");//找到根节点

        //    var files = data.SelectSingleNode("Files");//找到子节点 Files

        //    XmlElement newList;
        //    var list = files.SelectSingleNode(String.Format("List[@ProjectName='{0}']", entity.ProjectName));

        //    var item = xmlDoc.CreateElement("Item");//创建子节点 Item
        //    //item.SetAttribute("ProjectName", entity.ProjectName);//项目名称
        //    item.SetAttribute("LastWriteTime", entity.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss"));//修改时间
        //    item.SetAttribute("Size", entity.Size.ToString());//大小
        //    item.SetAttribute("Path", entity.Path);//路径

        //    if (list == null)//节点不存在
        //    {
        //        newList = xmlDoc.CreateElement("List");//创建List节点
        //        newList.SetAttribute("ProjectName", entity.ProjectName);//以此标记项目，大大减少Xml数据量

        //        newList.AppendChild(item);
        //        files.AppendChild(newList);//子项添加到 Files 节点中
        //    }
        //    else//节点已存在
        //    {
        //        list.AppendChild(item);
        //        files.AppendChild(list);//子项添加到 Files 节点中
        //    }

        //    data.AppendChild(files);//子项添加到 Data 根节点中
        //    xmlDoc.Save(FileName);//保存
        //}

        ///// <summary>
        ///// 编辑指定项
        ///// </summary>
        ///// <param name="entity">项目地址</param>
        //public void Modify(Files entity)
        //{
        //    var xmlDoc = new XmlDocument();
        //    xmlDoc.Load(FileName);
        //    var xmlNode = xmlDoc.SelectSingleNode(String.Format("Data/Files/Item[@Path='{0}']", entity.Path));

        //    if (xmlNode == null) return;
        //    //<Item Id="a17ec2d5-4f80-4dde-9a9c-a252900f7873" ProjectName="LI.Collaborate.AppII" ModifiedTime="2014-07-24 13:50:13" Size="4062" Path="D:\TDDOWNLOAD\Source\LI\LI.Collaborate\LI.Collaborate.AppII\Identity.aspx" />
        //    //<Item ProjectName="LI.Collaborate.AppII" ModifiedTime="2014-07-24 13:50:13" Size="4062" Path="D:\TDDOWNLOAD\Source\LI\LI.Collaborate\LI.Collaborate.AppII\Identity.aspx" />
        //    xmlNode.Attributes["LastWriteTime"].Value = entity.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
        //    xmlNode.Attributes["Size"].Value = entity.Size.ToString();

        //    xmlDoc.Save(FileName);
        //}

        ///// <summary>
        ///// 根据文件路径获取该文件上次信息
        ///// </summary>
        ///// <param name="path"></param>
        ///// <returns></returns>
        //public Files GetByPath(String path)
        //{
        //    var xmlDoc = new XmlDocument();
        //    xmlDoc.Load(FileName);
        //    var xmlNode = xmlDoc.SelectSingleNode(String.Format("Data/Files/Item[@Path='{0}']", path));

        //    if (xmlNode == null) return null;

        //    var files = new Files
        //    {
        //        ProjectName = xmlNode.Attributes["ProjectName"].Value,
        //        LastWriteTime = DateTime.Parse(xmlNode.Attributes["LastWriteTime"].Value),
        //        Size = Decimal.Parse(xmlNode.Attributes["Size"].Value),
        //        Path = xmlNode.Attributes["Path"].Value,
        //    };

        //    return files;
        //}

        ///// <summary>
        ///// 获取文件列表
        ///// </summary>
        ///// <returns></returns>
        //public IDictionary<Char, List<Files>> GetAllFilesByProjectName(String projectName)
        //{
        //    var dictionary = new Dictionary<Char, List<Files>>();
        //    var xmlDoc = new XmlDocument();

        //    //xmlDoc.Load(xmlStream);
        //    xmlDoc.Load(FileName);

        //    var filesList = xmlDoc.SelectSingleNode(String.Format("Data/Files/List[@ProjectName='{0}']", projectName));

        //    if (filesList == null) return dictionary;

        //    var xmlList = filesList.ChildNodes;

        //    foreach (XmlNode node in xmlList)
        //    {
        //        if (node.Attributes == null) continue;
        //        var path = node.Attributes["Path"].Value.ToUpper();
        //        var entity = new Files
        //        {
        //            ProjectName = projectName,
        //            LastWriteTime = DateTime.Parse(node.Attributes["LastWriteTime"].Value),
        //            Size = Decimal.Parse(node.Attributes["Size"].Value),
        //            Path = path,
        //        };
        //        var key = PublishFileVersionService.GetKey(path);

        //        if (!dictionary.ContainsKey(key))//创建一个键
        //            dictionary[key] = new List<Files>();

        //        dictionary[key].Add(entity);
        //    }
        //    return dictionary;
        //}

        //public IList<Files> GetAllFilesByProjectName(String projectName)
        //{
        //    var dictionary = new List<Files>();
        //    var xmlDoc = new XmlDocument();

        //    //xmlDoc.Load(xmlStream);
        //    xmlDoc.Load(FileName);
        //    var xmlList = xmlDoc.SelectSingleNode("Data/Files").ChildNodes;

        //    foreach (XmlNode node in xmlList)
        //    {
        //        if (node.Attributes == null) continue;
        //        var path = node.Attributes["Path"].Value.ToUpper();
        //        var entity = new Files
        //        {
        //            ProjectName = node.Attributes["ProjectName"].Value,
        //            ModifiedTime = DateTime.Parse(node.Attributes["ModifiedTime"].Value),
        //            Size = Decimal.Parse(node.Attributes["Size"].Value),
        //            Path = path,
        //        };

        //        dictionary.Add(entity);
        //    }
        //    return dictionary;
        //}

        #endregion

        #region Public

        /// <summary>
        /// 获取指定XPath表达式节点的值
        /// </summary>
        /// <param name="path">XPath表达式,
        /// 范例1: @"Skill/First/SkillItem", 等效于 @"//Skill/First/SkillItem"
        /// 范例2: @"Table[USERNAME='a']" , []表示筛选,USERNAME是Table下的一个子节点.
        /// 范例3: @"ApplyPost/Item[@itemName='岗位编号']",@itemName是Item节点的属性.
        /// </param>
        public string GetValue(String path)
        {
            var xmlDoc = new XmlDocument();
            xmlDoc.Load(path);

            var innerText = xmlDoc.GetElementsByTagName("Configuration")[0].InnerText;

            return innerText;
        }


        /// <summary>
        /// 在重新修改Xml结构之前此为依据创建Xml
        /// </summary>
        /// <returns></returns>
        public Boolean IsReset(String id)
        {
            if (!File.Exists(FileName))
                return true;

            var xmlDoc = new XmlDocument();
            xmlDoc.Load(FileName);
            var xmlNode = xmlDoc.SelectSingleNode(String.Format("Data[@Id='{0}']", id));
            if (xmlNode == null) return true;

            return !(xmlNode.Attributes["Id"].Value == XmlVersionId);
        }

        /// <summary>
        /// 文件夹或文件不存在则创建
        /// </summary>
        private void CreateFile()
        {
            var directoryInfo = new DirectoryInfo(FolderPath);//获取文件路径信息

            if (!directoryInfo.Exists) directoryInfo.Create();//如果文件夹不存在

            var result = IsReset(XmlVersionId);//确认是否需要重建

            if (!File.Exists(FileName) || result)//文件不存在或则需要重建配置文件
            {
                IList<Project> list = new List<Project>();
                if (File.Exists(FileName) && result)
                {
                    list = GetAllProject();
                    File.Delete(FileName);//首先将Xml文件删除
                }

                #region 创建默认Xml数据

                if (!File.Exists(FileName))
                {
                    //如果文件不存在则创建
                    var fs = File.Create(FileName);
                    fs.Close();
                    fs.Dispose();
                }

                var xmlDoc = new XmlDocument();
                var data = xmlDoc.CreateElement("Data");//创建根节点
                data.SetAttribute("Id", XmlVersionId);//用于判断是否重新生成Xml文件 

                var appSettings = xmlDoc.CreateElement("AppSettings");//连接字符串 节点

                var item = xmlDoc.CreateElement("Item");//创建子节点 Item
                item.SetAttribute("Id", Guid.NewGuid().ToString());
                item.SetAttribute("Value", "Data Source=192.168.2.227;Initial Catalog=master;User ID=dev;pwd=QWEqwe123");
                appSettings.AppendChild(item);//子项添加到 AppSettings 节点中
                data.AppendChild(appSettings);

                var project = xmlDoc.CreateElement("Project");//项目地址 节点

                foreach (var entity in list)
                {
                    item = xmlDoc.CreateElement("Item");//创建子节点 Item
                    item.SetAttribute("Id", entity.Id);
                    item.SetAttribute("IsDefault", entity.IsDefault);
                    item.SetAttribute("Path", entity.Path);
                    project.AppendChild(item);
                }

                data.AppendChild(project);

                //var files = xmlDoc.CreateElement("Files");//文件列表 节点
                //files.AppendChild(xmlDoc.CreateElement("List"));//创建子节点 List
                //data.AppendChild(files);

                xmlDoc.AppendChild(data);
                xmlDoc.Save(FileName);//保存

                #endregion
            }
        }

        #endregion
    }
}
